/*
** talker.c -- a datagram "client" demo
 *
 *
 *http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#datagram
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/timeb.h>
#include<stdint.h>

//#define Delay  10;

void  CreatePacket(unsigned char dest, unsigned char class, uint32_t packetnum, char buffer[])
{
    //unsigned char buffer[100];
     struct timeb tp;
     uint32_t time_1;

    buffer[0] = dest;
    buffer[5] = class;


    //Populate the packet number
    int cc;
    //buffer[6] = packetnum;
    for ( cc = 0; cc < 4; cc++)
    {
        buffer[6+cc] =  packetnum & 0xFF;
	packetnum >>= 8;
    }


    ftime(&tp);
    printf("time = %ld.%d\n",tp.time,tp.millitm);

    time_1 = tp.time;

    //Create Timestamp: milli seconds
    for ( cc = 0; cc < 2; cc++)
    {
	buffer[1+cc] =  tp.millitm;
	tp.millitm >>= 8;
     }

    //Create Timestamp: Seconds
     for ( cc = 0; cc < 2; cc++)
    {
	buffer[3+cc] = tp.time;
	tp.time >>= 8;
     }


    /*
    //Populate Timestamp

    uint32_t timestamp_milli;
    uint32_t timestamp_sec;

    //timestamp_milli = (unsigned int) buffer[2];
    timestamp_milli = 0;
    timestamp_milli = buffer[2];
    timestamp_milli  <<= 8;
    timestamp_milli = timestamp_milli | buffer[1];


    // timestamp_sec = (unsigned int) buffer[4];
    timestamp_sec = 0;
    timestamp_sec = buffer[4];
    timestamp_sec  <<= 8;
    timestamp_sec = timestamp_sec | buffer[3];

    printf("time = %u.%u\n",timestamp_sec, timestamp_milli);
    printf("time  m = %u.%u\n",(time_1&65535),timestamp_milli);
    */


    //Payload
    int i;
    for ( i = 10; i < 100; i++) {
        buffer[i] = i-10;
    }

    //return buffer;
}

//#define SERVERPORT "4950"    // the port users will be connecting to

int main(int argc, char *argv[])
{
    int sockfd;
    struct addrinfo hints, *servinfo, *p;
    int rv;
    int numbytes;
    int portno;

     unsigned char buffer[100];
     uint32_t time_1;
     unsigned char address;
     unsigned char class;

     uint8_t packet_dest;
     uint8_t packet_class;

     uint32_t packetnum_dest1_be = 0;
     uint32_t packetnum_dest1_pre = 0;

     uint32_t packetnum_dest2_be = 0;
     uint32_t packetnum_dest2_pre = 0;
     uint32_t totalpackets = 0;

     uint32_t packetnum;

     struct timeb start_time, end_time;
     float start_time_f, end_time_f, diff_time_f;

    int Delay = 10;    //Delay in milliseconds between packets



    if (argc != 3) {
        fprintf(stderr,"usage: talker hostname port\n");
        exit(1);
    }

     portno = atoi(argv[2]);
     printf("Port number:  %i",portno);

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;

    if ((rv = getaddrinfo(argv[1],argv[2], &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

    // loop through all the results and make a socket
    for(p = servinfo; p != NULL; p = p->ai_next) {
        if ((sockfd = socket(p->ai_family, p->ai_socktype,
                p->ai_protocol)) == -1) {
            perror("talker: socket");
            continue;
        }

        break;
    }

    if (p == NULL) {
        fprintf(stderr, "talker: failed to bind socket\n");
        return 2;
    }

    int packetcount;
    for (packetcount = 0; packetcount < 1500; packetcount++)
    {


        // 80 percent of the packets are garbage, 10 percent are for dest 1, 10 percent are for dest2
        packet_dest = (rand() % 100);

        //printf("Packet_dest: %i\n",packet_dest);

        if (packet_dest < 80)
        {
            //Destination Address
            address = ((rand() % 255) & 0xFF);
        }else if (packet_dest < 90)
        {
            //Destination Address
            address = 51;
        }else
        {
            //Destination Address
            address = 119;
        }

        //Class
        packet_class = (rand() % 100);

        if (packet_class < 75)
        {
            class = 10; //Best effort - 75%
        }else
        {
            class = 1;  //Premium - 25%
        }

     packetnum = 0;
     if (address == 51)
     {
         if (class == 10)
         {
            packetnum_dest1_be++;
            packetnum = packetnum_dest1_be;
         }else
         {
            packetnum_dest1_pre++;
            packetnum = packetnum_dest1_pre;
         }
     }else if (address == 119)
     {
         if (class == 10)
         {
            packetnum_dest2_be++;
             packetnum = packetnum_dest2_be;
         }else
         {
            packetnum_dest2_pre++;
            packetnum = packetnum_dest2_pre;
         }
     }else
     {
       totalpackets ++;
       packetnum = totalpackets;
     }


     //printf("Address:  %u\n",buffer[0]);
    // printf("Class: %u\n",buffer[5]);
    // printf("Packetnum: %u\n",packetnum);


     CreatePacket(address,  class,  packetnum,buffer);


        if ((numbytes = sendto(sockfd, buffer, 100, 0,
                p->ai_addr, p->ai_addrlen)) == -1) {
            perror("talker: sendto");
            exit(1);
        }


        //freeaddrinfo(servinfo);

        printf("talker: sent %d bytes to %s\n", numbytes, argv[1]);

        //sleep(1);

        //Implement a delay in milliseconds
        ftime(&start_time);
        ftime(&end_time);
        //start_time_f = start_time.time + (start_time.millitm/1000.0);
        //end_time_f = end_time.time + (end_time.millitm/1000.0);

        diff_time_f = (end_time.time -  start_time.time) + (end_time.millitm/1000.0);
        diff_time_f = diff_time_f - (start_time.millitm/1000.0);

        printf("calc : %f\n ", diff_time_f);

         while(diff_time_f < (Delay/1000.0))
         {
              ftime(&end_time);
              diff_time_f = (end_time.time -  start_time.time) + (end_time.millitm/1000.0);
              diff_time_f = diff_time_f - (start_time.millitm/1000.0);
         }

    }

    sleep(5);

    //Send two termination packets
    packetnum_dest1_pre ++;
    CreatePacket(51,1,packetnum_dest1_pre,buffer);
    buffer[10] = 255;
     if ((numbytes = sendto(sockfd, buffer, 100, 0,
                p->ai_addr, p->ai_addrlen)) == -1) {
            perror("talker: sendto");
            exit(1);
        }



    packetnum_dest2_pre ++;
    CreatePacket(119,1,packetnum_dest2_pre,buffer);
    buffer[10] = 255;
     if ((numbytes = sendto(sockfd, buffer, 100, 0,
                p->ai_addr, p->ai_addrlen)) == -1) {
            perror("talker: sendto");
            exit(1);
        }

    printf("Packetnum: %i\n",packetnum_dest1_be);
    printf("Packetnum: %i\n",packetnum_dest1_pre);
    printf("Packetnum: %i\n",packetnum_dest2_be);
    printf("Packetnum: %i\n",packetnum_dest2_pre);

    close(sockfd);

    return 0;
}
